/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

int Keyword_import( struct ZlangRuntime *rt )
{
	struct ZlangTokenDataUnitHeader	*token_info = NULL ;
	char				*token = NULL ;
	struct ZlangImportFile		*import_file = NULL ;
	char				*env_path = NULL ;
	ZlangImportObjectsFunction	*ZlangImportObjects = NULL ;
	
	int				nret = 0 ;
	
	for( ; ; )
	{
		TRAVELTOKEN( rt , token_info , token )
		if( token_info->token_type == TOKEN_TYPE_END_OF_STATEMENT )
		{
			break;
		}
		else if( token_info->token_type != TOKEN_TYPE_IDENTIFICATION )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect identification" )
			return ZLANG_ERROR_SYNTAX;
		}
		
		import_file = (struct ZlangImportFile *)ZLMALLOC( sizeof(struct ZlangImportFile) ) ;
		if( import_file == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for import_file" )
			return ZLANG_ERROR_ALLOC;
		}
		
		memset( import_file->import_filename , 0x00 , sizeof(import_file->import_filename) );
		env_path = getenv("ZLANG_HOME") ;
#if ( defined __linux ) || ( defined __unix )
		if( env_path )
			snprintf( import_file->import_filename , sizeof(import_file->import_filename)-1 , "%s/zobject/zobjects_%s.so" , env_path , token );
		else
			snprintf( import_file->import_filename , sizeof(import_file->import_filename)-1 , "%s/zobject/zobjects_%s.so" , getenv("HOME") , token );
#elif ( defined _WIN32 )
		if( env_path )
			snprintf( import_file->import_filename , sizeof(import_file->import_filename)-1 , "%s\\zobject\\zobjects_%s.dll" , env_path , token );
		else
			snprintf( import_file->import_filename , sizeof(import_file->import_filename)-1 , "C:\\Program Files\\zlang\\zobject\\zobjects_%s.dll" , token );
#endif

#if ( defined __linux ) || ( defined __unix )
		import_file->open_handler = dlopen( import_file->import_filename , RTLD_NOW|RTLD_GLOBAL ) ;
		if( import_file->open_handler == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_DLOPEN , "dlopen[%s] failed , dlerror[%s]" , import_file->import_filename , dlerror() )
			ZLFREE( import_file );
			return ZLANG_ERROR_DLOPEN;
		}
		
		ZlangImportObjects = dlsym( import_file->open_handler , "ZlangImportObjects" ) ;
		if( ZlangImportObjects == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_DLSYM , "dlsym 'ZlangImportClazzes' in file[%s] failed" , import_file->import_filename )
			ZLFREE( import_file );
			return ZLANG_ERROR_DLSYM;
		}
#elif ( defined _WIN32 )
		import_file->open_handler = LoadLibrary( import_file->import_filename ) ;
		if( import_file->open_handler == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_DLOPEN , "LoadLibrary[%s] failed[%d]" , import_file->import_filename , ERRNO )
			ZLFREE( import_file );
			return ZLANG_ERROR_DLOPEN;
		}

		ZlangImportObjects = (ZlangImportObjectsFunction *)GetProcAddress( import_file->open_handler , "ZlangImportObjects" ) ;
		if( ZlangImportObjects == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_DLSYM , "GetProcAddress 'ZlangImportObjects' in file[%s] failed" , import_file->import_filename )
			ZLFREE( import_file );
			return ZLANG_ERROR_DLSYM;
		}
#endif

		nret = ZlangImportObjects( rt ) ;
		if( nret )
		{
#if ( defined __linux ) || ( defined __unix )
			dlclose( import_file->open_handler );
#elif ( defined _WIN32 )
			FreeLibrary( import_file->open_handler );
#endif
			ZLFREE( import_file );
			return ZLANG_ERROR_IMPORT_OBJECTS;
		}
		
		list_add_tail( & (import_file->this_import_file) , & (rt->import_files_list) );
	}
	
	return 0;
}

